/**
 * ============================================
 * 认证路由模块 - auth.js
 *
 * 功能说明：
 * - 提供完整的用户认证系统API接口
 * - 包含用户注册、登录、密码重置、验证码发送等功能
 * - 使用JWT进行身份验证，bcrypt进行密码加密
 * - 集成图形验证码和邮件验证码双重验证机制
 *
 * 安全特性：
 * - 密码使用bcrypt哈希存储，避免明文存储
 * - JWT token过期机制，增强安全性
 * - 图形验证码防止暴力破解
 * - 邮件验证码用于重要操作验证
 * - 参数验证和错误处理完善
 *
 * 路由前缀：/api/auth（在app.js中注册时指定）
 * 示例接口：POST /api/auth/login, POST /api/auth/register
 *
 * 响应格式：
 * - 成功：{status: 0, msg: '成功消息', data: 数据}
 * - 失败：{status: 1, msg: '错误消息', data: null}
 * ============================================
 */

// 引入Express框架 - 用于创建路由和处理HTTP请求
const express = require('express');
// 引入bcryptjs库 - 用于密码哈希和验证，提供安全的密码存储
const bcrypt = require('bcryptjs');
// 引入jsonwebtoken库 - 用于生成和验证JWT令牌，实现无状态认证
const jwt = require('jsonwebtoken');
// 引入express-validator库 - 用于请求参数验证和错误处理
const { body, validationResult } = require('express-validator');
// 引入数据库操作函数 - 从database配置模块导入常用的数据库操作
const { query, get, insert, update } = require('../config/database');
// 引入Redis验证码相关函数 - 用于存储和验证图形验证码、邮件验证码
const { storeCaptcha, verifyCaptcha, storeEmailCode, verifyEmailCode } = require('../config/redis');
// 引入邮件服务函数 - 用于生成和发送邮件验证码
const { generateEmailCode, sendEmailCode } = require('../config/email');
// 引入svg-captcha库 - 用于生成图形验证码图片
const svgCaptcha = require('svg-captcha');

/**
 * 创建Express路由实例
 * 功能：定义认证相关的所有API端点
 * 在app.js中通过app.use('/api/auth', router)注册此路由
 */
const router = express.Router();

/**
 * ====================
 * 验证码生成函数
 * ====================
 * 功能：使用svg-captcha库生成图形验证码
 * 特点：生成包含干扰线和易识别字符的SVG图片验证码
 * 安全性：排除易混淆字符，统一小写处理，增强用户体验
 *
 * @returns {Object} 包含验证码图片、文本和ID的对象
 *   - captcha_img: Base64编码的SVG图片，可直接在img标签中使用
 *   - sys_captcha: 验证码文本（小写），用于验证用户输入
 *   - captcha_id: 唯一标识符，用于在Redis中存储和检索验证码
 */
const generateCaptcha = () => {
  /**
   * 使用svg-captcha库创建验证码
   * 配置参数说明：
   * - size: 4 - 验证码长度为4个字符
   * - ignoreChars: '0o1iIl' - 排除易混淆的字符（数字0、字母o、数字1、字母i、字母I、字母l）
   * - noise: 3 - 添加3条干扰线，增加识别难度
   * - color: true - 使用彩色验证码，提高可读性
   * - background: '#f8f9fa' - 设置浅灰色背景
   * - width: 120 - 图片宽度120像素
   * - height: 40 - 图片高度40像素
   * - fontSize: 36 - 字体大小36像素
   */
  const captcha = svgCaptcha.create({
    size: 4,                    // 验证码长度
    ignoreChars: '0o1iIl',      // 排除易混淆字符
    noise: 3,                   // 干扰线数量
    color: true,                // 彩色验证码
    background: '#f8f9fa',      // 背景色
    width: 120,                 // 宽度
    height: 40,                 // 高度
    fontSize: 36,               // 字体大小
  });
  
  /**
   * 返回验证码数据对象
   * 包含三个关键信息：
   * 1. 验证码图片（Base64格式，可直接在前端显示）
   * 2. 验证码文本（统一转为小写，不区分大小写验证）
   * 3. 验证码ID（唯一标识，用于后续验证）
   */
  return {
    // 将SVG数据转换为Base64格式的data URL，便于前端直接使用
    captcha_img: `data:image/svg+xml;base64,${Buffer.from(captcha.data).toString('base64')}`,
    // 验证码文本统一转为小写，实现不区分大小写的验证
    sys_captcha: captcha.text.toLowerCase(),
    // 生成唯一ID：时间戳 + 随机数，确保每次生成的ID都不同
    captcha_id: Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
  };
};

/**
 * ====================
 * 验证码接口
 * ====================
 * 接口：GET /captcha
 * 功能：生成并返回图形验证码，用于防止自动化攻击和暴力破解
 * 安全性：验证码存储在Redis中，有过期时间，一次性使用
 * 流程：生成验证码 → 存储到Redis → 返回图片和ID给前端
 *
 * @param {Object} req - Express请求对象（不需要参数）
 * @param {Object} res - Express响应对象，返回验证码数据
 * @returns {JSON} 包含验证码图片和ID的响应数据
 */
router.get('/captcha', async (req, res) => {
  try {
    /**
     * 生成验证码
     * 调用generateCaptcha()函数生成包含图片、文本和ID的验证码对象
     */
    const captcha = generateCaptcha();
    
    /**
     * 将验证码存储到Redis
     * 功能：将验证码文本存储到Redis，设置过期时间（默认5分钟）
     * 安全性：验证码ID作为key，验证码文本作为value
     * 过期时间：从环境变量读取或使用默认300秒（5分钟）
     */
    const stored = await storeCaptcha(captcha.captcha_id, captcha.sys_captcha, process.env.CAPTCHA_EXPIRE || 300);
    
    // 检查验证码是否成功存储到Redis
    if (!stored) {
      return res.status(500).json({
        status: 1,
        msg: '验证码存储失败',
        data: null
      });
    }
    
    /**
     * 构建返回给前端的响应数据
     * 安全性考虑：不返回实际的验证码文本，只返回ID和图片
     * - captcha_img: Base64格式的验证码图片，前端可直接显示
     * - sys_captcha: 验证码ID，前端提交时需要携带此ID进行验证
     */
    const responseData = {
      captcha_img: captcha.captcha_img,
      sys_captcha: captcha.captcha_id
    };
    
    /**
     * 返回成功响应
     * 响应格式：{status: 0, msg: '成功消息', data: 验证码数据}
     */
    res.json({
      status: 0,
      msg: '获取验证码成功',
      data: responseData
    });
  } catch (error) {
    /**
     * 错误处理
     * 捕获验证码生成或存储过程中可能出现的错误
     */
    console.error('生成验证码失败:', error);
    
    /**
     * 返回错误响应
     * 响应格式：{status: 1, msg: '错误消息', data: null}
     * HTTP状态码：500（服务器内部错误）
     */
    res.status(500).json({
      status: 1,
      msg: '生成验证码失败',
      data: null
    });
  }
});

// ====================
// 用户登录接口
// ====================
router.post('/login', [
  body('username').notEmpty().withMessage('用户名不能为空'),
  body('password').notEmpty().withMessage('密码不能为空'),
  body('captcha').notEmpty().withMessage('验证码不能为空'),
  body('sys_captcha').notEmpty().withMessage('验证码ID不能为空')
], async (req, res) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.json({
        status: 1,
        msg: errors.array()[0].msg,
        data: null
      });
    }

    const { username, password, captcha, sys_captcha } = req.body;

    // 使用Redis验证验证码
    const isCaptchaValid = await verifyCaptcha(sys_captcha, captcha);
    if (!isCaptchaValid) {
      return res.json({
        status: 1,
        msg: '验证码错误或已过期',
        data: null
      });
    }

    // 查询用户信息
    const users = await query(
      'SELECT * FROM users WHERE username = ? OR email = ?',
      [username, username]
    );

    if (users.length === 0) {
      return res.json({
        status: 1,
        msg: '用户名或密码错误',
        data: null
      });
    }

    const user = users[0];

    // 验证密码
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.json({
        status: 1,
        msg: '用户名或密码错误',
        data: null
      });
    }

    // 更新最后登录时间
    await update(
      'UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?',
      [user.id]
    );

    // 生成JWT token
    const token = jwt.sign(
      { userId: user.id, username: user.username },
      process.env.JWT_SECRET,
      { expiresIn: process.env.JWT_EXPIRE }
    );

    // 返回用户信息（不包含密码）
    const { password: _, ...userWithoutPassword } = user;

    res.json({
      status: 0,
      msg: '登录成功',
      data: {
        user: userWithoutPassword,
        token
      }
    });

  } catch (error) {
    console.error('Login error:', error);
    res.status(500).json({
      status: 1,
      msg: '登录失败',
      data: null
    });
  }
});

// ====================
// 获取当前用户信息接口
// ====================
router.get('/current-user', async (req, res) => {
  try {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (!token) {
      return res.status(401).json({
        status: 1,
        msg: '需要认证token',
        data: null
      });
    }

    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    
    const users = await query(
      'SELECT id, username, email, country, name, avatar, created_at, last_login FROM users WHERE id = ?',
      [decoded.userId]
    );

    if (users.length === 0) {
      return res.status(404).json({
        status: 1,
        msg: '用户不存在',
        data: null
      });
    }

    res.json({
      status: 0,
      msg: '获取用户信息成功',
      data: users[0]
    });

  } catch (error) {
    console.error('Get current user error:', error);
    res.status(500).json({
      status: 1,
      msg: '获取用户信息失败',
      data: null
    });
  }
});

// ====================
// 用户注册接口
// ====================
router.post('/register', [
  body('username').isEmail().withMessage('请输入有效的邮箱地址'),
  body('password').notEmpty().withMessage('密码不能为空'),
  body('password_confirmation').notEmpty().withMessage('确认密码不能为空'),
  body('email_code').notEmpty().withMessage('邮箱验证码不能为空'),
  body('country').notEmpty().withMessage('国家不能为空')
], async (req, res) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.json({
        status: 1,
        msg: errors.array()[0].msg,
        data: null
      });
    }

    const { username, password, password_confirmation, email_code, country } = req.body;

    // 验证密码确认
    if (password !== password_confirmation) {
      return res.json({
        status: 1,
        msg: '两次密码不一致',
        data: null
      });
    }

    // 验证邮箱验证码
    const isEmailCodeValid = await verifyEmailCode(username, email_code);
    if (!isEmailCodeValid) {
      return res.json({
        status: 1,
        msg: '邮箱验证码错误或已过期',
        data: null
      });
    }

    // 检查用户名是否已存在
    const existingUsers = await query(
      'SELECT id FROM users WHERE username = ? OR email = ?',
      [username, username]
    );

    if (existingUsers.length > 0) {
      return res.json({
        status: 1,
        msg: '该邮箱已被注册',
        data: null
      });
    }

    // 哈希密码
    const hashedPassword = await bcrypt.hash(password, 12);

    // 创建新用户（username作为邮箱使用，同时将username保存到name字段作为昵称）
    const userId = await insert(
      'INSERT INTO users (username, email, password, country, name) VALUES (?, ?, ?, ?, ?)',
      [username, username, hashedPassword, country, username]
    );

    // 生成JWT token
    const token = jwt.sign(
      { userId, username },
      process.env.JWT_SECRET,
      { expiresIn: process.env.JWT_EXPIRE }
    );

    res.status(201).json({
      status: 0,
      msg: '注册成功',
      data: {
        user: { id: userId, username, email: username, country, name: username },
        token
      }
    });

  } catch (error) {
    console.error('Register error:', error);
    res.status(500).json({
      status: 1,
      msg: '注册失败',
      data: null
    });
  }
});

// ====================
// 获取重置密码邮箱验证码接口
// ====================
router.post('/reset-password/email-code', [
  body('username').isEmail().withMessage('请输入有效的邮箱地址'),
  body('captcha').notEmpty().withMessage('验证码不能为空'),
  body('sys_captcha').notEmpty().withMessage('验证码ID不能为空')
], async (req, res) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.json({
        status: 1,
        msg: errors.array()[0].msg,
        data: null
      });
    }

    const { username, captcha, sys_captcha } = req.body;

    // 验证图形验证码
    const isCaptchaValid = await verifyCaptcha(sys_captcha, captcha);
    if (!isCaptchaValid) {
      return res.json({
        status: 1,
        msg: '验证码错误或已过期',
        data: null
      });
    }

    // 检查邮箱是否已注册
    const existingUsers = await query(
      'SELECT id, username FROM users WHERE email = ? OR username = ?',
      [username, username]
    );

    if (existingUsers.length === 0) {
      // 安全考虑：不暴露邮箱是否注册的信息
      return res.json({
        status: 1,
        msg: '邮件发送失败，请检查邮箱后重试',
        data: null
      });
    }

    // 生成验证码
    const emailCode = generateEmailCode();
    
    // 发送邮件验证码
    const emailResult = await sendEmailCode(username, emailCode, '重置密码');

    if (!emailResult.success) {
      return res.status(500).json({
        status: 1,
        msg: '邮件发送失败，请稍后重试',
        data: null
      });
    }

    // 存储验证码到Redis，过期时间10分钟
    const stored = await storeEmailCode(username, emailCode, process.env.EMAIL_CODE_EXPIRE || 600);

    if (!stored) {
      return res.status(500).json({
        status: 1,
        msg: '验证码存储失败',
        data: null
      });
    }

    res.json({
      status: 0,
      msg: '验证码已发送至您的邮箱',
      data: null
    });

  } catch (error) {
    console.error('发送重置密码验证码失败:', error);
    res.status(500).json({
      status: 1,
      msg: '发送验证码失败',
      data: null
    });
  }
});

// ====================
// 重置密码接口
// ====================
router.post('/reset-password', [
  body('username').isEmail().withMessage('请输入有效的邮箱地址'),
  body('password').notEmpty().withMessage('密码不能为空'),
  body('password_confirmation').notEmpty().withMessage('确认密码不能为空'),
  body('email_code').notEmpty().withMessage('邮箱验证码不能为空')
], async (req, res) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.json({
        status: 1,
        msg: errors.array()[0].msg,
        data: null
      });
    }

    const { username, password, password_confirmation, email_code } = req.body;

    if (password !== password_confirmation) {
      return res.json({
        status: 1,
        msg: '两次密码不一致',
        data: null
      });
    }

    // 验证邮箱验证码
    const isEmailCodeValid = await verifyEmailCode(username, email_code);
    if (!isEmailCodeValid) {
      return res.json({
        status: 1,
        msg: '邮箱验证码错误或已过期',
        data: null
      });
    }

    // 检查用户是否存在
    const users = await query(
      'SELECT id, username FROM users WHERE email = ? OR username = ?',
      [username, username]
    );

    if (users.length === 0) {
      // 安全考虑：不暴露邮箱是否注册的信息
      return res.json({
        status: 1,
        msg: '密码重置失败，请检查验证码后重试',
        data: null
      });
    }

    const user = users[0];

    // 更新密码
    const hashedPassword = await bcrypt.hash(password, 12);
    await update(
      'UPDATE users SET password = ? WHERE email = ? OR username = ?',
      [hashedPassword, username, username]
    );

    res.json({
      status: 0,
      msg: '密码重置成功',
      data: null
    });

  } catch (error) {
    console.error('Reset password error:', error);
    res.status(500).json({
      status: 1,
      msg: '密码重置失败',
      data: null
    });
  }
});

// ====================
// 获取注册邮箱验证码接口
// ====================
router.post('/register/email-code', [
  body('username').isEmail().withMessage('请输入有效的邮箱地址'),
  body('captcha').notEmpty().withMessage('验证码不能为空'),
  body('sys_captcha').notEmpty().withMessage('验证码ID不能为空')
], async (req, res) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.json({
        status: 1,
        msg: errors.array()[0].msg,
        data: null
      });
    }

    const { username, captcha, sys_captcha } = req.body;

    // 验证图形验证码
    const isCaptchaValid = await verifyCaptcha(sys_captcha, captcha);
    if (!isCaptchaValid) {
      return res.json({
        status: 1,
        msg: '验证码错误或已过期',
        data: null
      });
    }

    // 检查邮箱是否已被注册
    const existingUsers = await query(
      'SELECT id FROM users WHERE email = ? OR username = ?',
      [username, username]
    );

    if (existingUsers.length > 0) {
      return res.json({
        status: 1,
        msg: '该邮箱已被注册',
        data: null
      });
    }

    // 生成验证码
    const emailCode = generateEmailCode();
    
    // 发送邮件验证码
    const emailResult = await sendEmailCode(username, emailCode, '注册');
console.log(emailResult)
    if (!emailResult.success) {
      return res.status(500).json({
        status: 1,
        msg: '邮件发送失败，请稍后重试',
        data: null
      });
    }

    // 存储验证码到Redis，过期时间10分钟
    const stored = await storeEmailCode(username, emailCode, process.env.EMAIL_CODE_EXPIRE || 600);
    
    if (!stored) {
      return res.status(500).json({
        status: 1,
        msg: '验证码存储失败',
        data: null
      });
    }

    res.json({
      status: 0,
      msg: '验证码已发送至您的邮箱',
      data: null
    });

  } catch (error) {
    console.error('发送注册验证码失败:', error);
    res.status(500).json({
      status: 1,
      msg: '发送验证码失败',
      data: null
    });
  }
});

// ====================
// 修改用户设置接口（支持基本信息和密码修改）
// ====================
router.put('/user_setting', async (req, res) => {
  try {
    const { avatar, name, old_password, password, confirm_password } = req.body;
    
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (!token) {
      return res.status(401).json({
        status: 1,
        msg: '需要认证token',
        data: null
      });
    }

    const decoded = jwt.verify(token, process.env.JWT_SECRET);

    // 判断是修改密码还是修改基本信息
    if (old_password) {
      // 修改密码流程
      if (!password || !confirm_password) {
        return res.json({
          status: 1,
          msg: '新密码和确认密码不能为空',
          data: null
        });
      }

      if (password !== confirm_password) {
        return res.json({
          status: 1,
          msg: '新密码和确认密码不一致',
          data: null
        });
      }

      // 查询当前用户信息
      const users = await query(
        'SELECT * FROM users WHERE id = ?',
        [decoded.userId]
      );

      if (users.length === 0) {
        return res.status(404).json({
          status: 1,
          msg: '用户不存在',
          data: null
        });
      }

      const user = users[0];

      // 验证旧密码
      const isOldPasswordValid = await bcrypt.compare(old_password, user.password);
      if (!isOldPasswordValid) {
        return res.json({
          status: 1,
          msg: '旧密码错误',
          data: null
        });
      }

      // 哈希新密码
      const hashedPassword = await bcrypt.hash(password, 12);

      // 更新密码和基本信息
      await update(
        'UPDATE users SET password = ?, avatar = ?, name = ? WHERE id = ?',
        [hashedPassword, avatar || user.avatar, name || user.name, decoded.userId]
      );

      res.json({
        status: 0,
        msg: '密码修改成功',
        data: null
      });
    } else {
      // 修改基本信息流程
      // 更新用户设置
      await update(
        'UPDATE users SET avatar = ?, name = ? WHERE id = ?',
        [avatar, name, decoded.userId]
      );

      res.json({
        status: 0,
        msg: '用户设置更新成功',
        data: null
      });
    }

  } catch (error) {
    console.error('User setting error:', error);
    res.status(500).json({
      status: 1,
      msg: '更新用户设置失败',
      data: null
    });
  }
});

module.exports = router;